package org.goldenport.g3.channels.dropbox;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.mime.HttpMultipartMode;
import org.apache.http.entity.mime.MultipartEntity;
import org.apache.http.entity.mime.content.StringBody;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;

import com.dropbox.client.Authenticator;
import com.dropbox.client.DropboxClient;
import com.dropbox.client.DropboxException;

/**
 * @since   Jul. 19, 2010
 * @version Aug. 28, 2010
 * @author  ASAMI, Tomoharu
 **/
public class G3DropboxClient extends DropboxClient {
    /**
     * Config needs to have settings for "server", "content_server", and "port" (which should be a Long),
     * and auth should be ready to work with an access key.
     */
    @SuppressWarnings("unchecked")
    public G3DropboxClient(Map config, Authenticator auth) {
        super(config, auth);
    }

    /**
     * Write a file in the user's Dropbox.
     */
    @SuppressWarnings("unchecked")
    public HttpResponse writeFile(String root, String to_path, String filename, String string) throws DropboxException
    {
        String path = "/files/" + root + to_path;
        
        HttpClient client = getClient();

        try {
            String target = buildFullURL(secureProtocol, content_host, this.port, buildURL(path, API_VERSION, null));
            HttpPost req = new HttpPost(target);
            // this has to be done this way because of how oauth signs params
            // first we add a "fake" param of file=path of *uploaded* file
            // THEN we sign that.
            List nvps = new ArrayList();
            nvps.add(new BasicNameValuePair("file", filename));
            req.setEntity(new UrlEncodedFormEntity(nvps, HTTP.UTF_8));
            auth.sign(req);

            // now we can add the real file multipart and we're good
            MultipartEntity entity = new MultipartEntity(HttpMultipartMode.BROWSER_COMPATIBLE);
            StringBody bin = new StringBody(string);
            entity.addPart("file", bin);
            // this resets it to the new entity with the real file
            req.setEntity(entity);

            HttpResponse resp = client.execute(req);
            
            resp.getEntity().consumeContent();
            return resp;
        } catch(Exception e) {
            throw new DropboxException(e);
        }
    }
}
